package network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Traite un client sur le serveur.
 * @author Guillaume Poças
 */
public class KrakenThread implements Runnable{
	
	private Thread thread;
	private Socket socket;
	private PrintWriter out; // pour gestion du flux de sortie
	private BufferedReader in; // pour gestion du flux d'entree
	private KrakenServer krakenServer;
	private int numClient = 0;
	private KrakenCommandInterpreter rci;
	private boolean run;
	
	final Lock lock = new ReentrantLock();
	final Condition turn = lock.newCondition();

	/**
	 * Constructeur.
	 * @param s
	 * @param krakenServer
	 */
	public KrakenThread(Socket s, KrakenServer krakenServer){
		this.krakenServer = krakenServer;
		socket = s;
		rci = null;
		run = true;
		try{
			// fabrication d'une variable permettant l'utilisation du flux de sortie avec des string
			out = new PrintWriter(socket.getOutputStream());
			// fabrication d'une variable permettant l'utilisation du flux d'entree avec des string
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			// ajoute le flux de sortie dans la liste et recuperation de son numero
			numClient = krakenServer.addClient(out);
		}
		catch(IOException e){
			e.printStackTrace(); //
		}
	
		thread = new Thread(this);
		thread.start();
	}

	@Override
	public synchronized void run(){
		String message = "";
		// on indique dans la console la connection d'un nouveau client
		System.out.println("Un nouveau client s'est connecte, no " + numClient);
		rci = new KrakenCommandInterpreter(this);
		try{
			while(run){
				message = in.readLine();
				if(!message.equalsIgnoreCase("")){
					if(rci != null)	rci.interpret(message);
					message = "";
				}
			}
		}
		catch(Exception e){
			e.printStackTrace(); //
		}
		
		finally{ // finally se produira le plus souvent lors de la deconnexion du client
			//System.out.println("Le client no " + numClient + " s'est deconnecte");
			//krakenServer.delClient(numClient);
			try{
				System.out.println("Le client no " + numClient + " s'est deconnecte");
				krakenServer.delClient(numClient); 
				socket.close();
			}
			catch(IOException e){
				e.printStackTrace(); //
			}
		}
	}
	
	public void setKrakenCommandInterpreter(KrakenCommandInterpreter rci){ this.rci = rci; }
	
	public KrakenServer getKrakenServer(){ return this.krakenServer; }
	
	/**
	 * Envoi un message au client.
	 * @param cmd
	 */
	public void sendCommand(String cmd){
		out.println(cmd);
		out.flush();
	}

	public Socket getSocket() { return socket; }
	public void setSocket(Socket socket) { this.socket = socket; }
	
	public boolean getRunState(){ return this.run;	}
	public void setRunOff(){ this.run = false;	}
	
}